﻿using System;
using System.Configuration;
using System.IO;
using System.Linq;
using CI.Models.Data;
using log4net;

namespace XmlModelPackager
{
    public class RegionsXmlGenerator : XmlGeneratorBase, IXmlGenerator
    {
        public string Region { get; private set; }
        private readonly ILog _logger = LogManager.GetLogger(typeof(RegionsXmlGenerator));
        public RegionsXmlGenerator(string region)
            : base(new FileInfo("map_" + region + ".xml"), "Regions")
        {
            Region = region;
        }

        public RegionsXmlGenerator()
            : base(new FileInfo("map_Complete.xml"), "Regions")
        {
            Region = "*";
        }

        protected TyrannisDataContext GetDataContext()
        {
            return new TyrannisDataContext(ConfigurationManager.ConnectionStrings["TyrannisDB"].ConnectionString);
        }

        public void GenerateXml()
        {
            using (var ctx = GetDataContext())
            {
                IQueryable<mapRegion> regions = null;

                regions = Region=="*" ? ctx.mapRegions : ctx.mapRegions.Where(r => r.regionName == Region);

                if (regions.Count() == 0) throw new ArgumentException("There is no region called " + Region);

                foreach (var region in regions)
                {
                    BeginElement("Region");

                    _logger.DebugFormat("Processing {0}:{1}", region.regionID, region.regionName);

                    WriteAttributes(region, "regionID", "regionName", "factionID");

                    foreach (var constellation in ctx.mapConstellations.Where(c => c.regionID == region.regionID))
                    {
                        WriteConstellation(ctx, constellation);
                    }

                    WriteRegionJumps(ctx, region);

                    EndElement();
                }
            }
        }

        private void WriteConstellation(TyrannisDataContext ctx, mapConstellation constellation)
        {
            BeginElement("Constellation");

            _logger.DebugFormat("Processing {0}:{1}", constellation.constellationID,
                                constellation.constellationName);

            WriteAttributes(constellation, "constellationID", "constellationName", "factionID");

            foreach (
                var solarSystem in
                    ctx.mapSolarSystems.Where(s => s.constellationID == constellation.constellationID))
            {
                WriteSolarSystem(solarSystem);
            }


            EndElement();
        }

        private void WriteSolarSystem(mapSolarSystem solarSystem)
        {
            BeginElement("SolarSystem");

            _logger.DebugFormat("Processing {0}:{1}", solarSystem.solarSystemID,
                                solarSystem.solarSystemName);

            WriteAttributes(solarSystem, "solarSystemID", "solarSystemName", "luminosity", "border",
                            "fringe", "corridor", "hub", "international", "regional", "constellation",
                            "security", "factionID", "sunTypeID", "securityClass");
            EndElement();
        }

        private void WriteRegionJumps(TyrannisDataContext ctx, mapRegion region)
        {
            foreach(var regionJump in ctx.mapRegionJumps.Where(r=>r.fromRegionID == region.regionID || r.toRegionID == region.regionID))
            {
                if (regionJump.fromRegionID==region.regionID)
                {
                    BeginElement("JumpFrom");
                    WriteAttribute(regionJump.toRegionID, "toRegionID");
                    EndElement();
                }
                else
                {
                    BeginElement("JumpTo");
                    WriteAttribute(regionJump.fromRegionID, "fromRegionID");
                    EndElement();
                }
            }
        }
    }
}